package com.wolfeyes.framework.config;

import com.wolfeyes.framework.shiro.JwtCredentialsMatcher;
import com.wolfeyes.framework.shiro.JwtFilter;
import com.wolfeyes.framework.shiro.realms.CustomizeRealm;

import lombok.extern.slf4j.Slf4j;

import org.apache.shiro.authc.credential.CredentialsMatcher;
import org.apache.shiro.mgt.DefaultSessionStorageEvaluator;
import org.apache.shiro.mgt.DefaultSubjectDAO;
import org.apache.shiro.realm.Realm;
import org.apache.shiro.spring.LifecycleBeanPostProcessor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.servlet.Filter;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;

/**
 * @description Shiro安全认证权限框架配置信息
 * @see Talk is cheap, Show me the code. -- Linus Torvalds
 * @title 配置shiro安全框架
 * @author yanyljava
 * @create 2022-01-14 21:25
 */
@Slf4j
// javaconfig配置
@Configuration
public class ShiroConfig {

	/**
	 * @description lifecycleBeanPostProcessor是负责生命周期的 , 初始化和销毁的类 (可选)
	 * @title 注入方式加载（static方法优先加载）
	 * @title Shiro生命周期处理器
     * @author yanyljava
     * @since 2018年07月12日上午11:37:39
     * @return LifecycleBeanPostProcessor
	 */
	@Bean(name = "lifecycleBeanPostProcessor")
	public static LifecycleBeanPostProcessor getLifecycleBeanPostProcessor() {
		
		log.info("===============(1)Shiro生命周期周期处理器设置");
		return new LifecycleBeanPostProcessor();
	}
	
	//创建shiroFilter
	@Bean("shiroFilter")
	public ShiroFilterFactoryBean getShiroFilterFactoryBean(DefaultWebSecurityManager defaultWebSecurityManager){
		ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();

		//给shiroFilter设置安全管理器
		shiroFilterFactoryBean.setSecurityManager(defaultWebSecurityManager);

		//配置受限资源
		Map<String, String> map = new LinkedHashMap<>();
		map.put("/sysUser/**", "anon");//放行
		map.put("/images/**", "anon");//放行图片查询
		map.put("/captcha/**", "anon");//放行验证码请求
		map.put("/**", "jwt");//请求这个资源需要认证与授权

		// 添加自己的过滤器并且取名为jwt
		Map<String, Filter> filterMap = new HashMap<String, Filter>(1);
		filterMap.put("jwt", new JwtFilter());
		shiroFilterFactoryBean.setFilters(filterMap);

		//设置认证规则
		shiroFilterFactoryBean.setFilterChainDefinitionMap(map);
		return shiroFilterFactoryBean;
	}

	//创建安全管理器
	@Bean
	public DefaultWebSecurityManager getDefaultWebSecurityManager(Realm realm){
		DefaultWebSecurityManager defaultWebSecurityManager = new DefaultWebSecurityManager();

		//给安全管理器设置realm
		defaultWebSecurityManager.setRealm(realm);

		//关闭shiro自带的session，使得不保存登录状态（无状态的），每次使用token进行验证
		DefaultSubjectDAO subjectDAO = new DefaultSubjectDAO();
		DefaultSessionStorageEvaluator defaultSessionStorageEvaluator = new DefaultSessionStorageEvaluator();
		// shiro默认使用cookie来存sessionID，我们既然采用了token方式，那么这里可以禁用了
		defaultSessionStorageEvaluator.setSessionStorageEnabled(false);
		subjectDAO.setSessionStorageEvaluator(defaultSessionStorageEvaluator);
		defaultWebSecurityManager.setSubjectDAO(subjectDAO);
		
		// 60分钟(此设置会覆盖容器（tomcat）的会话过期时间设置)
		// sessionManager.setGlobalSessionTimeout(60*60*1000);
		// shiro默认使用cookie来存sessionID，我们既然采用了基于token的认证方式，那么这里可以禁用了
		//sessionManager.setSessionIdCookieEnabled(false);

		return defaultWebSecurityManager;
	}
	
	//shiro凭证校验器（其实就是密码的校验器）
	//@Bean(name = "credentialsMatcher")
	public CredentialsMatcher getCredentialsMatcher() {
		JwtCredentialsMatcher jwtCredentialsMatcher = new JwtCredentialsMatcher();
		return jwtCredentialsMatcher;
		
	}

	// 创建自定义realm => CustomizeRealm对象 注入到Spring IOC容器当中
	@Bean(name = "realm")
	public Realm getRealm(){
		CustomizeRealm realm = new CustomizeRealm();
		//realm.setCredentialsMatcher(getCredentialsMatcher());
		
		return realm;
	}

}
